# 在绑定属性时，如果我们直接把属性暴露出去，虽然写起来
# 很简单，但是，没办法检查参数，导致可以把成绩随便改：

class Student(object):
    pass
s=Student()
s.score=999

#这样绑定的属性可以随意修改，而且类型不能检查会导致异常
print(s.score)


class Studengt1(object):
    def get_score(self):
        print("get_score:",self.score)
        return self.score

    def set_score(self,value):
        print("input:",value)
        if not isinstance(value,int):
            print("please input int class")
            return
        if value < 0 or value>100:
            print('please input a 0-100 num')
            return
        self.score=value

st=Studengt1()
st.set_score(60)
st.get_score()
st.set_score(-1)
st.get_score()
st.set_score('asd')
st.get_score()

# st.get_score()
# 但是，上面的调用方法又略显复杂，没有直接用属性这么直接简单。
# 有没有既能检查参数，又可以用类似属性这样简单的方式来访问类的变量呢
# 还记得装饰器（decorator）可以给函数动态加上功能吗？
# 对于类的方法，装饰器一样起作用。Python内置的@property
# 装饰器就是负责把一个方法变成属性调用的：
class Student2(object):

    @property
    def score(self):
        return self._score

    @score.setter
    def score(self, value):
        if not isinstance(value, int):
            raise ValueError('score must be an integer!')
        if value < 0 or value > 100:
            raise ValueError('score must between 0 ~ 100!')
        self._score = value


st2=Student2()
st2.score=60
print(st2.score)


class Student3(object):

    @property
    def birth(self):
        return self._birth

    @birth.setter
    def birth(self, value):
        self._birth = value

    @property
    def age(self):
        return 2015 - self._birth
#上面的birth是可读写属性，而age就是一个只读属性，因为age可以根据birth和当前时间计算出来。



